/**
   The MIT License (MIT)

   Copyright (c) 2014 thelostcode

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   THE SOFTWARE.
 */

#include "DMSNavigation.h"

#include <QIcon>
#include <QPainter>
#include <QVBoxLayout>
#include <QMouseEvent>
#include <QPaintEvent>
#include <QFontMetrics>

const int CONTENT_MARGIN_LEFT = 16;
const int CONTENT_MARGIN_RIGHT = 16;
const int CONTENT_MARGIN = CONTENT_MARGIN_LEFT + CONTENT_MARGIN_RIGHT;
const int DMS_ITEM_MINIMUM_SIZE = 40 + CONTENT_MARGIN;
const int DMS_ITEM_MAXIMUM_SIZE = 120 + CONTENT_MARGIN;
const int DMS_ITEM_ICON_MARGIN = 8;

namespace PNG
{
   const unsigned char Body[215] =
   {
	   0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,
	   0x0D,0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x01,0x00,0x00,
	   0x00,0x26,0x08,0x02,0x00,0x00,0x00,0x8A,0xDE,0x66,0x50,
	   0x00,0x00,0x00,0x01,0x73,0x52,0x47,0x42,0x00,0xAE,0xCE,
	   0x1C,0xE9,0x00,0x00,0x00,0x04,0x67,0x41,0x4D,0x41,0x00,
	   0x00,0xB1,0x8F,0x0B,0xFC,0x61,0x05,0x00,0x00,0x00,0x09,
	   0x70,0x48,0x59,0x73,0x00,0x00,0x0E,0xC3,0x00,0x00,0x0E,
	   0xC3,0x01,0xC7,0x6F,0xA8,0x64,0x00,0x00,0x00,0x1A,0x74,
	   0x45,0x58,0x74,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,
	   0x00,0x50,0x61,0x69,0x6E,0x74,0x2E,0x4E,0x45,0x54,0x20,
	   0x76,0x33,0x2E,0x35,0x2E,0x31,0x31,0x47,0xF3,0x42,0x37,
	   0x00,0x00,0x00,0x46,0x49,0x44,0x41,0x54,0x18,0x57,0x63,
	   0x30,0xB5,0xB4,0x64,0x08,0x0C,0x0B,0x67,0x70,0xF3,0xF6,
	   0x61,0x70,0xF3,0xF2,0x66,0x70,0x45,0xC7,0x9E,0x5E,0x0C,
	   0x2E,0xC8,0xD8,0xC3,0x13,0x8C,0x9D,0x91,0xB1,0xBB,0x07,
	   0x18,0x3B,0xC1,0xB0,0x9B,0x3B,0x1C,0x3B,0xC2,0xB0,0xAB,
	   0x1B,0x1C,0x3B,0x80,0xB0,0x8B,0x2B,0x0A,0xB6,0x07,0x61,
	   0x67,0x17,0x30,0xD6,0x33,0x34,0x04,0x00,0x5C,0x76,0x1E,
	   0xCF,0x7D,0xBC,0xF8,0x0F,0x00,0x00,0x00,0x00,0x49,0x45,
	   0x4E,0x44,0xAE,0x42,0x60,0x82
   };

   const unsigned char BorderLeft[215] =
   {
	   0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,
	   0x0D,0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x01,0x00,0x00,
	   0x00,0x26,0x08,0x02,0x00,0x00,0x00,0x8A,0xDE,0x66,0x50,
	   0x00,0x00,0x00,0x01,0x73,0x52,0x47,0x42,0x00,0xAE,0xCE,
	   0x1C,0xE9,0x00,0x00,0x00,0x04,0x67,0x41,0x4D,0x41,0x00,
	   0x00,0xB1,0x8F,0x0B,0xFC,0x61,0x05,0x00,0x00,0x00,0x09,
	   0x70,0x48,0x59,0x73,0x00,0x00,0x0E,0xC3,0x00,0x00,0x0E,
	   0xC3,0x01,0xC7,0x6F,0xA8,0x64,0x00,0x00,0x00,0x1A,0x74,
	   0x45,0x58,0x74,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,
	   0x00,0x50,0x61,0x69,0x6E,0x74,0x2E,0x4E,0x45,0x54,0x20,
	   0x76,0x33,0x2E,0x35,0x2E,0x31,0x31,0x47,0xF3,0x42,0x37,
	   0x00,0x00,0x00,0x46,0x49,0x44,0x41,0x54,0x18,0x57,0x63,
	   0x30,0xB5,0xB4,0x64,0x88,0x4E,0x48,0x64,0x08,0x0C,0x0B,
	   0x67,0x08,0x0C,0x0D,0x63,0x08,0x40,0xC7,0x21,0xA1,0x0C,
	   0xFE,0xC8,0x38,0x38,0x04,0x8C,0xFD,0x90,0x71,0x50,0x30,
	   0x18,0xFB,0xC2,0x70,0x60,0x10,0x1C,0xFB,0xC0,0x70,0x40,
	   0x20,0x1C,0x7B,0x83,0xB0,0x7F,0x00,0x0A,0xF6,0x02,0x61,
	   0x3F,0x7F,0x30,0xD6,0x33,0x34,0x04,0x00,0xBB,0x7F,0x23,
	   0x70,0x3D,0x75,0xDA,0x5F,0x00,0x00,0x00,0x00,0x49,0x45,
	   0x4E,0x44,0xAE,0x42,0x60,0x82
   };

   const unsigned char BorderRight[208] =
   {
	   0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,
	   0x0D,0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x01,0x00,0x00,
	   0x00,0x26,0x08,0x02,0x00,0x00,0x00,0x8A,0xDE,0x66,0x50,
	   0x00,0x00,0x00,0x01,0x73,0x52,0x47,0x42,0x00,0xAE,0xCE,
	   0x1C,0xE9,0x00,0x00,0x00,0x04,0x67,0x41,0x4D,0x41,0x00,
	   0x00,0xB1,0x8F,0x0B,0xFC,0x61,0x05,0x00,0x00,0x00,0x09,
	   0x70,0x48,0x59,0x73,0x00,0x00,0x0E,0xC3,0x00,0x00,0x0E,
	   0xC3,0x01,0xC7,0x6F,0xA8,0x64,0x00,0x00,0x00,0x1A,0x74,
	   0x45,0x58,0x74,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,
	   0x00,0x50,0x61,0x69,0x6E,0x74,0x2E,0x4E,0x45,0x54,0x20,
	   0x76,0x33,0x2E,0x35,0x2E,0x31,0x31,0x47,0xF3,0x42,0x37,
	   0x00,0x00,0x00,0x3F,0x49,0x44,0x41,0x54,0x18,0x57,0x65,
	   0xC3,0xC9,0x09,0xC0,0x20,0x14,0x05,0xC0,0x57,0x91,0xE0,
	   0xF6,0x17,0x97,0x83,0x87,0xA4,0xFF,0x92,0x44,0x45,0xC1,
	   0x64,0x60,0x10,0x55,0xD1,0x9E,0x17,0x52,0x2A,0x24,0x17,
	   0xF0,0x77,0xCA,0xA0,0x6B,0xFA,0xD7,0x35,0xEE,0xA2,0x67,
	   0xD8,0x59,0x4E,0x3F,0x12,0x5F,0xDD,0x4C,0xB3,0xB1,0xB6,
	   0x03,0x90,0x17,0x18,0xDF,0x51,0xCA,0x88,0xA5,0x00,0x00,
	   0x00,0x00,0x49,0x45,0x4E,0x44,0xAE,0x42,0x60,0x82
   };

   const unsigned char BodyHover[226] =
   {
	   0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,
	   0x0D,0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x01,0x00,0x00,
	   0x00,0x26,0x08,0x02,0x00,0x00,0x00,0x8A,0xDE,0x66,0x50,
	   0x00,0x00,0x00,0x01,0x73,0x52,0x47,0x42,0x00,0xAE,0xCE,
	   0x1C,0xE9,0x00,0x00,0x00,0x04,0x67,0x41,0x4D,0x41,0x00,
	   0x00,0xB1,0x8F,0x0B,0xFC,0x61,0x05,0x00,0x00,0x00,0x09,
	   0x70,0x48,0x59,0x73,0x00,0x00,0x0E,0xC3,0x00,0x00,0x0E,
	   0xC3,0x01,0xC7,0x6F,0xA8,0x64,0x00,0x00,0x00,0x1A,0x74,
	   0x45,0x58,0x74,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,
	   0x00,0x50,0x61,0x69,0x6E,0x74,0x2E,0x4E,0x45,0x54,0x20,
	   0x76,0x33,0x2E,0x35,0x2E,0x31,0x31,0x47,0xF3,0x42,0x37,
	   0x00,0x00,0x00,0x51,0x49,0x44,0x41,0x54,0x18,0x57,0x4D,
	   0xC6,0xB9,0x0D,0xC0,0x30,0x08,0x40,0x51,0x26,0x8A,0xE4,
	   0x22,0x85,0x27,0xF0,0x01,0xF8,0x8C,0x94,0x26,0xD9,0x7F,
	   0x8D,0x00,0x05,0x4A,0xF1,0xF5,0x3E,0x9C,0x31,0xC2,0xFD,
	   0xBC,0xC0,0x6B,0x43,0xDB,0x97,0x69,0xCD,0x65,0x92,0x2A,
	   0xD1,0x98,0xF6,0xF8,0x57,0xC2,0x3E,0xEC,0xAB,0x2A,0xD5,
	   0xD6,0xED,0x8B,0x2A,0x15,0x6E,0xAE,0x96,0x89,0xDD,0x2C,
	   0x26,0x55,0x4A,0x48,0xEE,0x11,0xC2,0x07,0x57,0x24,0x22,
	   0x24,0xCE,0xB6,0x33,0xC8,0x00,0x00,0x00,0x00,0x49,0x45,
	   0x4E,0x44,0xAE,0x42,0x60,0x82
   };

   unsigned char BodyClicked[237] =
   {
	   0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,
	   0x0D,0x49,0x48,0x44,0x52,0x00,0x00,0x00,0x01,0x00,0x00,
	   0x00,0x26,0x08,0x02,0x00,0x00,0x00,0x8A,0xDE,0x66,0x50,
	   0x00,0x00,0x00,0x01,0x73,0x52,0x47,0x42,0x00,0xAE,0xCE,
	   0x1C,0xE9,0x00,0x00,0x00,0x04,0x67,0x41,0x4D,0x41,0x00,
	   0x00,0xB1,0x8F,0x0B,0xFC,0x61,0x05,0x00,0x00,0x00,0x09,
	   0x70,0x48,0x59,0x73,0x00,0x00,0x0E,0xC3,0x00,0x00,0x0E,
	   0xC3,0x01,0xC7,0x6F,0xA8,0x64,0x00,0x00,0x00,0x1A,0x74,
	   0x45,0x58,0x74,0x53,0x6F,0x66,0x74,0x77,0x61,0x72,0x65,
	   0x00,0x50,0x61,0x69,0x6E,0x74,0x2E,0x4E,0x45,0x54,0x20,
	   0x76,0x33,0x2E,0x35,0x2E,0x31,0x31,0x47,0xF3,0x42,0x37,
	   0x00,0x00,0x00,0x5C,0x49,0x44,0x41,0x54,0x18,0x57,0x3D,
	   0xC9,0xD1,0x0D,0x40,0x30,0x00,0x05,0xC0,0xB7,0x84,0x98,
	   0x82,0x28,0x8A,0x6A,0x29,0x5A,0x54,0x4D,0x6A,0x0B,0xA3,
	   0x91,0x97,0xF0,0x71,0x5F,0x07,0xA9,0x14,0x5C,0x38,0xC8,
	   0x1F,0x11,0xEE,0xE5,0xE3,0xF9,0xFB,0x6E,0xDE,0x03,0x4D,
	   0xEB,0x46,0xD6,0xAF,0x34,0x2C,0x8E,0xCC,0xBC,0x90,0xB6,
	   0x13,0xA9,0xD1,0x52,0x67,0x06,0x6A,0xB5,0x41,0xD3,0x6B,
	   0x54,0x6D,0x47,0x42,0x36,0x28,0x6A,0x89,0xAC,0x2C,0x91,
	   0xA4,0x29,0xC2,0x75,0xFF,0x72,0x21,0x1E,0xD2,0x08,0x1E,
	   0x83,0x94,0x8C,0x15,0x5A,0x00,0x00,0x00,0x00,0x49,0x45,
	   0x4E,0x44,0xAE,0x42,0x60,0x82
   };

   const unsigned int BodySize = 215;
   const unsigned int BorderLeftSize = 215;
   const unsigned int BorderRightSize = 208;
   const unsigned int BodyHoverSize = 226;
   const unsigned int BodyClickedSize = 237;
}

//-----------------------------------------------------------------------------
// DMSItem
//-----------------------------------------------------------------------------
class DMSItem 
{
public:
   DMSItem()
      : isClicked(false)
   {
   }

   QString title;
   bool isClicked;
   QRect lastRect;
   QPixmap icon;

public:
   inline int width(const QFontMetrics& fontMetrics) 
   { return fontMetrics.width(title); }
};

//-----------------------------------------------------------------------------
// DMSNavigationBar
//-----------------------------------------------------------------------------
class DMSNavigationBar : public QWidget
{
public:
   explicit DMSNavigationBar(DMSNavigation* q, QWidget* parent = NULL, Qt::WindowFlags flags = 0);
   ~DMSNavigationBar();

   int addTab(const QString& text);
   int addTab(const QIcon& icon, const QString& text);

   int insertTab(int index, const QString& text);
   int insertTab(int index, const QIcon& icon, const QString& text);

   void removeTab(int index);

   QString tabText(int index) const;
   void setTabText(int index, const QString& text);

   QIcon tabIcon(int index) const;
   void setTabIcon(int index, const QIcon& icon);

   DMSNavigation::HorizontalAlignment horizontalAlignment() const;
   void setHorizontalAlignment(DMSNavigation::HorizontalAlignment alignment);

   int count() const;
   int currentIndex() const;

public slots:
   void setCurrentIndex(int index);

protected:
   virtual void enterEvent(QEvent* event);
   virtual void leaveEvent(QEvent* event);
   virtual void paintEvent(QPaintEvent* event);
   virtual void mouseMoveEvent(QMouseEvent* event);
   virtual void mousePressEvent(QMouseEvent* event);

private:
   void paintItem(const QRectF& rect, QPainter* painter, int index, int reserved);
   void paintContent(const QRectF& rect, QPainter* painter, int index, int reserved);
   void paintLeftBorder(const QRectF& rect, QPainter* painter);
   void paintRightBorder(const QRectF& rect, QPainter* painter);

   int indexByPosition(const QPoint& position);
   int navigationWidth();
   int navigationItemWidth(int index, int reserved);

protected:
   DMSNavigation* q_ptr = nullptr;

private:
   int m_nCurrentIndex;
   QList<DMSItem*> m_itemList;
   DMSNavigation::HorizontalAlignment m_alignment = DMSNavigation::AlignCenter;
};

//-----------------------------------------------------------------------------
// DMSNavigation
//-----------------------------------------------------------------------------
DMSNavigation::DMSNavigation(QWidget* parent, Qt::WindowFlags flags)
   : QWidget(parent, flags)
   , navigation(new DMSNavigationBar(this, 0))
{
   QVBoxLayout *vl = new QVBoxLayout();
   vl->setMargin(0);
   vl->setSpacing(0);
   vl->addWidget(navigation, 0, Qt::AlignTop);
   vl->addWidget(&stacked, 1);
   setLayout(vl);
}

DMSNavigation::~DMSNavigation()
{
   delete navigation;
}

int DMSNavigation::addTab(QWidget* widget, const QString& text)
{
   stacked.addWidget(widget);
   int r = navigation->addTab(text);
   if (count() == 1) setCurrentIndex(0);
   return r;
}

int DMSNavigation::addTab(QWidget* widget, const QIcon& icon, const QString& text)
{
   stacked.addWidget(widget);
   int r = navigation->addTab(icon, text);
   if (count() == 1) setCurrentIndex(0);
   return r;
}

int DMSNavigation::insertTab(int index, QWidget* widget, const QString& text)
{
   stacked.insertWidget(index, widget);
   return navigation->insertTab(index, text);
}

int DMSNavigation::insertTab(int index, QWidget* widget, const QIcon& icon, const QString& text)
{
   stacked.insertWidget(index, widget);
   return navigation->insertTab(index, icon, text);
}

void DMSNavigation::removeTab(int index)
{
   navigation->removeTab(index);
   stacked.removeWidget(stacked.widget(index));
}

QString DMSNavigation::tabText(int index) const
{
   return navigation->tabText(index);
}

void DMSNavigation::setTabText(int index, const QString& text)
{
   navigation->setTabText(index, text);
}

QIcon DMSNavigation::tabIcon(int index) const
{
   return navigation->tabIcon(index);
}

void DMSNavigation::setTabIcon(int index, const QIcon& icon)
{
   navigation->setTabIcon(index, icon);
}

DMSNavigation::HorizontalAlignment DMSNavigation::horizontalAlignment() const
{
   return navigation->horizontalAlignment();
}

void DMSNavigation::setHorizontalAlignment(DMSNavigation::HorizontalAlignment alignment)
{
   navigation->setHorizontalAlignment(alignment);
}

int DMSNavigation::count() const
{
   return navigation->count();
}

int DMSNavigation::currentIndex() const
{
   return navigation->currentIndex();
}

void DMSNavigation::setCurrentIndex(int index)
{
   int current = navigation->currentIndex();
   navigation->setCurrentIndex(index);
   if (current != navigation->currentIndex())
   {
      stacked.setCurrentIndex(index);
      emit currentChanged(index);
   }
}

//-----------------------------------------------------------------------------
// DMSNavigationBar
//-----------------------------------------------------------------------------
DMSNavigationBar::DMSNavigationBar(DMSNavigation* q, QWidget* parent, Qt::WindowFlags flags)
   : QWidget(parent, flags)
   , m_nCurrentIndex(-1)
   , m_itemList(QList<DMSItem*>())
   , m_alignment(DMSNavigation::AlignCenter)
   , q_ptr(q)
{
   setMouseTracking(true);
   setFixedHeight(38);
}

DMSNavigationBar::~DMSNavigationBar()
{
   qDeleteAll(m_itemList);
}

int DMSNavigationBar::addTab(const QString& text)
{
   return addTab(QIcon(), text);
}

int DMSNavigationBar::addTab(const QIcon& icon, const QString& text)
{
   DMSItem* item = new DMSItem();
   item->icon = icon.pixmap(QSize(16, 16));
   item->title = text;
   m_itemList.append(item);
   update();
   return count() - 1;
}

int DMSNavigationBar::insertTab(int index, const QString& text)
{
   return insertTab(index, QIcon(), text);
}

int DMSNavigationBar::insertTab(int index, const QIcon& icon, const QString& text)
{
   DMSItem* item = new DMSItem();
   item->icon = icon.pixmap(QSize(16, 16));
   item->title = text;
   m_itemList.insert(index, item);
   update();
   return index;
}

void DMSNavigationBar::removeTab(int index)
{
   delete m_itemList.takeAt(index);
   update();
}

QString DMSNavigationBar::tabText(int index) const
{
   return m_itemList[index]->title;
}

void DMSNavigationBar::setTabText(int index, const QString& text)
{
   m_itemList[index]->title = text;
   update();
}

QIcon DMSNavigationBar::tabIcon(int index) const
{
   return m_itemList[index]->icon;
}

void DMSNavigationBar::setTabIcon(int index, const QIcon& icon)
{
   m_itemList[index]->icon = icon.pixmap(QSize(16, 16));
   update();
}

DMSNavigation::HorizontalAlignment DMSNavigationBar::horizontalAlignment() const
{
   return m_alignment;
}

void DMSNavigationBar::setHorizontalAlignment(DMSNavigation::HorizontalAlignment alignment)
{
   m_alignment = alignment;
   update();
}

int DMSNavigationBar::count() const
{
   return m_itemList.count();
}

int DMSNavigationBar::currentIndex() const
{
   return m_nCurrentIndex;
}

void DMSNavigationBar::setCurrentIndex(int index)
{
   if (index != -1 && index != m_nCurrentIndex)
   {
      if (m_nCurrentIndex != -1)
         m_itemList[m_nCurrentIndex]->isClicked = false;

      m_itemList[index]->isClicked = true;
      m_nCurrentIndex = index;
      update();
   }
}

void DMSNavigationBar::enterEvent(QEvent* event)
{
   QWidget::enterEvent(event);
   update();
}

void DMSNavigationBar::leaveEvent(QEvent* event)
{
   QWidget::enterEvent(event);
   update();
}

void DMSNavigationBar::paintEvent(QPaintEvent*)
{
   QPainter p(this);

   // background
   static QPixmap pixContent;
   if (pixContent.isNull())
      pixContent.loadFromData(PNG::Body, PNG::BodySize);
   p.drawPixmap(rect(), pixContent);

   int navWidth = navigationWidth();
   const int navHeight = rect().height();

   int margin = 0;
   switch (m_alignment)
   {
   case DMSNavigation::AlignLeft:
      margin = 0;
      break;
   case DMSNavigation::AlignRight:
      margin = rect().width() - navWidth;
   default:
      margin = rect().width() / 2 - navWidth / 2;
      break;
   }

   double x = margin;

   // outer - inner look & feel
   if (count())
      paintRightBorder(QRectF(x - 1, 0, 1, navHeight), &p);

   // content
   for (int i = 0; i < m_itemList.count(); i++)
   {
      int itemWidth = navigationItemWidth(i, x);
      paintItem(QRectF(x, 0, itemWidth, navHeight), &p, i, x);
      x += itemWidth;
   }

   // outer - inner look & feel
   if (count())
      paintLeftBorder(QRectF(x, 0, 1, navHeight), &p);
}

void DMSNavigationBar::mouseMoveEvent(QMouseEvent* event)
{
   QWidget::mouseMoveEvent(event);
   update();
}

void DMSNavigationBar::mousePressEvent(QMouseEvent* event)
{
   QWidget::mousePressEvent(event);
   if (event->button() != Qt::LeftButton)
      return;

   int index = indexByPosition(event->pos());
   q_ptr->setCurrentIndex(index);
}

void DMSNavigationBar::paintItem(const QRectF& rect, QPainter* painter, int index, int reserved)
{
   paintLeftBorder(QRectF(rect.x(), rect.top(), 1, rect.height()), painter);
   paintContent(QRectF(rect.x() + 1, rect.top(), rect.width() - 2, rect.height()), painter, index, reserved);
   paintRightBorder(QRectF(rect.x() + rect.width() - 1, rect.top(), 1, rect.height()), painter);
   m_itemList[index]->lastRect = rect.toRect();
}

void DMSNavigationBar::paintLeftBorder(const QRectF& rect, QPainter* painter)
{
   static QPixmap pixLeft;
   if (pixLeft.isNull())
      pixLeft.loadFromData(PNG::BorderLeft, PNG::BorderLeftSize);
   painter->drawPixmap(rect.toRect(), pixLeft);
}

void DMSNavigationBar::paintContent(const QRectF& rect, QPainter* painter, int index, int reserved)
{
   bool isClicked = m_itemList[index]->isClicked;

   if (isClicked || !rect.contains(mapFromGlobal(QCursor::pos())))
   {
      if (isClicked)
      {
         static QPixmap pixContent;
         if (pixContent.isNull())
            pixContent.loadFromData(PNG::BodyClicked, PNG::BodyClickedSize);
         painter->drawPixmap(rect.toRect(), pixContent);
      }
      else
      {
         static QPixmap pixContent;
         if (pixContent.isNull())
            pixContent.loadFromData(PNG::Body, PNG::BodySize);
         painter->drawPixmap(rect.toRect(), pixContent);
      }
   }
   else
   {
      static QPixmap pixContent;
      if (pixContent.isNull())
         pixContent.loadFromData(PNG::BodyHover, PNG::BodyHoverSize);
      painter->drawPixmap(rect.toRect(), pixContent);
   }


   QString strText = m_itemList[index]->title;

   QRectF textTargetRect = rect;
   QRectF iconTargetRect = rect;
   if (!m_itemList[index]->icon.isNull())
   {
      iconTargetRect.setX(iconTargetRect.x() + DMS_ITEM_ICON_MARGIN / 2 + m_itemList[index]->icon.width() / 2);
      iconTargetRect.setY(iconTargetRect.y() + rect.height() / 2 - m_itemList[index]->icon.height() / 2);
      
      iconTargetRect.setWidth(m_itemList[index]->icon.width());
      iconTargetRect.setHeight(m_itemList[index]->icon.height());
      
      textTargetRect.setX(iconTargetRect.right() - DMS_ITEM_ICON_MARGIN);
      
      painter->drawPixmap(iconTargetRect.toRect(), m_itemList[index]->icon);
   }

   if (textTargetRect.width() < navigationItemWidth(index, reserved))
      strText = fontMetrics().elidedText(strText, Qt::TextElideMode::ElideRight, textTargetRect.width() - CONTENT_MARGIN);

   painter->setPen(Qt::white);
   painter->drawText(textTargetRect, strText, QTextOption(Qt::AlignCenter));
}

void DMSNavigationBar::paintRightBorder(const QRectF& rect, QPainter* painter)
{
   static QPixmap pixRight;
   if (pixRight.isNull())
      pixRight.loadFromData(PNG::BorderRight, PNG::BorderRightSize);
   painter->drawPixmap(rect.toRect(), pixRight);
}

int DMSNavigationBar::indexByPosition(const QPoint& position)
{
   for (int i = 0; i < m_itemList.count(); i++)
   {
      if (m_itemList[i]->lastRect.contains(position))
         return i;
   }
   return -1;
}

int DMSNavigationBar::navigationWidth()
{
   int result = 0;
   for (int i = 0; i < m_itemList.count(); i++)
   {
      result += navigationItemWidth(i, result);
   }

   return result;
}

int DMSNavigationBar::navigationItemWidth(int index, int reserved)
{
   DMSItem *item = m_itemList[index];
   int result = item->width(fontMetrics());

   int available = rect().width() - reserved;
   
   int iconWidth = 0;
   if (!item->icon.isNull())
      iconWidth = item->icon.width() + DMS_ITEM_ICON_MARGIN;

   result = result + CONTENT_MARGIN_LEFT + CONTENT_MARGIN_RIGHT + iconWidth;
   result = qMax(DMS_ITEM_MINIMUM_SIZE, result);
   result = qMin(DMS_ITEM_MAXIMUM_SIZE, result);
   result = qMin(result, available);

   return result;
}
